package com;

import java.util.ArrayList;

import com.Exception.NotExistingException;

/**
 * Modèle d'un prédicat :  predicat(arg1,arg2...)
 * @author florent
 */
public class Modele {
	
	private String predicat;  									//nom du prédicat
	private boolean negative = false;							//validité du modèle
	private Type[] arguments;	//liste des arguments
	
	private static ArrayList<Modele> EXISTING_MODELES = new ArrayList<Modele>(); //liste statique des modèles éxistants
	
	/**
	 * Constuit un modèle
	 * @param predicat nom du prédicat
	 * @param negative validité du prédicat
	 */
	private Modele(String predicat,boolean negative, String ...args ){
		
		this.predicat = predicat;
		this.negative = negative;
		this.arguments = new Type[args.length];
		for(int i=0; i<args.length;++i)
			arguments[i] = Type.newType(args[i]);
	}

	/**
	 * Retourne le nom du prédicat
	 * @return le nom du prédicat
	 */
	public String getPredicat(){
		return predicat;
	}
	
	/**
	 * Retourne la validité du modèle
	 * @return la validité du modèle
	 */
	public boolean isNegative(){
		return negative;
	}
	
	/**
	 * Retourne la liste des arguments
	 * @return la liste des arguments
	 */
	public Type[] getArguments(){
		return arguments;
	}
	
	/**
	 * Retourne l'arité du modèle
	 * @return l'arité du modèle
	 */
	public int getArite(){
		return arguments.length;
	}
	
	/**
	 * Permet de comparer deux modèles <br/>
	 * critères : prédicat et négativité.
	 * @param modele2
	 * @return vrai si les modèles sont égaux
	 */
	public boolean equals(Modele modele2){
		return predicat.equals(modele2.getPredicat()) && (negative == modele2.negative);
	}
	
	/**
	 * Permet de comparer un modèle à un patron de modèle<br/>
	 * critères : prédicat et négativité.
	 * @param predicat nom du prédicat
	 * @param negative validité du modèle
	 * @return vrai si les modèles sont égaux
	 */
	public boolean equals(String predicat, boolean negative){
		return this.predicat.equals(predicat) && (this.negative == negative);
	}
	
	/**
	 * Méthode statique permettant d'éviter les doublons, en ajoutant dans une liste statique de modèles.
	 * @param predicat prédicat du modèle a insérer/ou deja existant
	 * @param negative validité du modèle
	 * @return le modèle créé ou recupéré
	 */
	public static Modele newModele(String predicat,boolean truth, String ... args){
		boolean exists = false;
		
		predicat = predicat.replace(" ", "");
		
		Modele modele = null;
		
		for(Modele c : EXISTING_MODELES){
			if(c.equals(predicat,!truth)){
				exists = true;
				modele = c;
				break;
			}
		}
		if(exists == false){ //si non trouvé
			modele = new Modele(predicat,!truth,args);
			EXISTING_MODELES.add(modele);
		}
		
		return modele;
	}
	
	/**
	 * Retourne le modèle dont le prédicat est passé en paramètre
	 * @param predicat prédicat du modèle
	 * @return le modèle trouve
	 * @throws NotExistingException si le modèle n'éxiste pas
	 */
	public static Modele getmodele(String predicat) throws NotExistingException{
		for(Modele c : EXISTING_MODELES){
			if(c.predicat.equals(predicat))
				return c;
		}
		throw new NotExistingException("modele innexistante"); // si non trouvé
	}
	
	/**
	 * Méthode statique permettant de récupérer la liste complete des modèles
	 * @return liste complete des modèles
	 */
	public static ArrayList<Modele> getModeles(){
		return EXISTING_MODELES;
	}
	
	public String toString(){
		StringBuffer sb = new StringBuffer();
		
		if(negative)
			sb.append("!");
		
		sb.append(predicat);
		
		return sb.toString();
	}
	
}
